package models.bill;

import models.UUIDModel;
import models.admin.AdminUser;
import models.constants.DeletedStatus;
import models.contract.BankCard;
import models.contract.Contract;
import models.enums.FeeType;
import models.enums.OwnerType;
import models.enums.VoucherStatus;
import models.user.User;
import org.hibernate.SQLQuery;
import org.hibernate.annotations.Index;
import org.hibernate.transform.Transformers;
import play.Logger;
import util.common.ConvertUtil;
import util.common.DateUtil;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 工单信息  (每次维修等服务后 生成一个 支付工单)
 */
@Entity(name = "bl_vouchers")
@org.hibernate.annotations.Table(appliesTo = "bl_vouchers", indexes = {@Index(name = "idx_vouchers_busi_recd_id", columnNames = {"business_record_id"})})
public class Voucher extends UUIDModel {

    /**
     * 归属的合同.
     */
    @JoinColumn(name = "contract_id")
    @ManyToOne
    public Contract contract;

    /**
     * 相关用户
     */
    @JoinColumn(name = "user_id")
    @ManyToOne
    public User user;

    /**
     * 相关AdminUser
     */
    @JoinColumn(name = "admin_user_id")
    @ManyToOne
    public AdminUser adminUser;

    /**
     * 凭证所属月份
     * 2016-12
     */
    @Column(name = "belong_month", length = 20)
    public String belongMonth;

    /**
     * 凭证状态.
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "voucher_status", length = 10)
    public VoucherStatus voucherStatus;

    /**
     * 费用类型
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "fee_type", length = 15)
    public FeeType feeType;

    /**
     * 账单金额
     */
    @Column(name = "amount")
    public BigDecimal amount;

    /**
     * 对应的账单明细.
     */
    @JoinColumn(name = "bill_detail_id")
    @ManyToOne
    public BillDetail billDetail;

    /**
     * 对象的业务对象ID.
     */
    @Column(name = "business_record_id", length = 32)
    public String businessRecordId;

    /**
     * 摘要.
     */
    @Column(name = "remark", length = 250)
    public String remark;

    /**
     * @param id
     * @return
     */
    public static Voucher findByVoucherId(String id) {
        return Voucher.find("id = ? and deleted = ? ", id, DeletedStatus.UN_DELETED).first();
    }

    /**
     * @param businessRecordId
     * @return
     */
    public static Voucher findByBusinessRecordId(String businessRecordId) {
        return Voucher.find("businessRecordId = ? and deleted = ? ", businessRecordId, DeletedStatus.UN_DELETED).first();

    }

    /**
     * 按合同查询,所有未结算的凭证,
     * 账单结束时间之前未结算的凭证
     *
     * @param contractId
     * @return
     */
    public static List<Voucher> loadByContractIdAndNOPAYED(String contractId , Date billEndDate) {
        return Voucher.find("contract.id = ? and deleted = ? and (voucherStatus = ? or voucherStatus =? ) and  createdAt < ?", contractId, DeletedStatus.UN_DELETED, VoucherStatus.BILLED, VoucherStatus.UN_BILL, billEndDate).fetch();
    }

    /**
     * 检查是否生成物物业/租金凭证
     *
     * @param contract
     * @param feeType
     * @param belongMonth
     * @return
     */
    public static Boolean checkVoucher(Contract contract, FeeType feeType, String belongMonth) {
        return Voucher.count("contract = ? and feeType = ? and belongMonth = ? and deleted = 0", contract, feeType, belongMonth) > 0;
    }

    public static List<Voucher> findByUserForThisMonth(User user) {
        return Voucher.find("  deleted = ? and createdAt > ?", DeletedStatus.UN_DELETED, DateUtil.firstDayOfMonth()).fetch();
    }

    //生成物业费凭证和租金凭证
    public static String generateVoucher() {
        String resultMsg = "";
        //查询所有合同期内的合同, 上月25日到本月25日
        Date today = DateUtil.getTomorrow(); // 当前时间 明天零点 演示用
//        Date today = DateUtil.getAppointDate(25); // 获取当前月的25日
//        Date today = DateUtil.stringToDate("2017-02-25 00:00:00", "yyyy-MM-dd HH:mm:ss"); // 指定2017-02-25 ,演示用
//        Date beganDate = DateUtil.getLastMonth(today); // 获取上上个月25日
//        Date beganDate = DateUtil.getBeforeMonth(today ,-1); //获取指定日期往前推一个月,为开始日期
        Date beganDate = DateUtil.firstDayOfMonth();//当月第一天
        String beganAt = DateUtil.dateToString(beganDate, "yyyy-MM-dd HH:mm:ss");
        String endAt = DateUtil.dateToString(today, "yyyy-MM-dd HH:mm:ss");

        Logger.info("开始时间和结束时间--------------------------------beganAt : %s | endAt : %s " ,beganAt , endAt);

        //合同期包含上月25日到上上月25日的合同
        String sqlSelect = "select a.id from co_contracts a  " +
                "    where a.deleted = 0 " +
                "    and ((a.begin_at >= '" + beganAt + "' and a.begin_at < '" + endAt + "')  " +
                "      or (a.end_at >= '" + beganAt + "' and a.end_at < '" + endAt + "')   " +
                "      or (a.begin_at <= '" + beganAt + "' and a.end_at >= '" + endAt + "'))";

        Query query = Contract.em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, String>> contractIdList = query.getResultList();
        if (contractIdList != null && contractIdList.size() > 0) {
            long propertyNum = 0l;
            long rentNum = 0l;
            for (Map<String, String> map : contractIdList) {
                String contractId = map.get("id");
                Contract contract = Contract.findByContractId(contractId);
                Logger.info("------------------------contract:%s", contract);
                BankCard bankCard = BankCard.findByContract(contract);
                User user = null;
                if (bankCard != null && bankCard.user != null) {
                    user = bankCard.user;
                }
                Logger.info("------------------------user:%s", user);
                String belongMonth = DateUtil.dateToString(today, "yyyy-MM");
                //检查当月的物业凭证是否已经生成
                if (!Voucher.checkVoucher(contract, FeeType.PROPERTY_FEE, belongMonth)) {

                    Voucher voucherProperty = new Voucher();
                    voucherProperty.contract = contract;
                    voucherProperty.feeType = FeeType.PROPERTY_FEE;
                    voucherProperty.amount = contract.propertyFee;
                    voucherProperty.voucherStatus = VoucherStatus.UN_BILL;
                    voucherProperty.belongMonth = belongMonth;
                    voucherProperty.user = user;
                    voucherProperty.deleted = DeletedStatus.UN_DELETED;
                    voucherProperty.createdAt = new Date();
                    voucherProperty.belongCompany = contract.belongCompany != null ? contract.belongCompany : null;
                    voucherProperty.save();
                    propertyNum += 1;
                }
                //检测业主类型是否是租户,并且当月没有生成过租金凭证
                if (contract.ownerType == OwnerType.TENANT && !Voucher.checkVoucher(contract, FeeType.RENT, belongMonth)) {
                    Voucher voucherTenant = new Voucher();
                    voucherTenant.contract = contract;
                    voucherTenant.feeType = FeeType.RENT;
                    voucherTenant.amount = contract.monthlyRent;
                    voucherTenant.voucherStatus = VoucherStatus.UN_BILL;
                    voucherTenant.belongMonth = belongMonth;
                    voucherTenant.user = user;
                    voucherTenant.deleted = DeletedStatus.UN_DELETED;
                    voucherTenant.createdAt = new Date();
                    voucherTenant.belongCompany = contract.belongCompany != null ? contract.belongCompany : null ;
                    voucherTenant.save();
                    rentNum += 1;
                }
            }
            resultMsg = "本次共生成物业凭证:" + propertyNum + " 份 , 租金凭证 :" + rentNum + "份 ,执行结束!";
            Logger.info("------------------------------" + resultMsg + "------------------------------");

        } else {
            resultMsg = "目前没有凭证需要生成";
            Logger.info("------------------------------"+resultMsg+"------------------------------");
        }
        return resultMsg ;
    }
}
